/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    tm1650_simple.c
  * @brief   Simplified TM1650 4-digit 7-segment display driver implementation
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include <stdint.h>

/* USER CODE BEGIN 0 */

// TM1650 I2C Address
#define TM1650_I2C_ADDR    0x48

// TM1650 Commands
#define TM1650_CMD_DATA_CMD      0x48    // 数据命令 0x48H
#define TM1650_CMD_DISPLAY_ON    0x01    // 开显示
#define TM1650_CMD_DISPLAY_OFF   0x00    // 关显示

// TM1650 Display positions
#define TM1650_POS1    0x68    // First digit
#define TM1650_POS2    0x6A    // Second digit  
#define TM1650_POS3    0x6C    // Third digit
#define TM1650_POS4    0x6E    // Fourth digit

// 7-segment display patterns (common cathode)
#define TM1650_DIGIT_0    0x3F
#define TM1650_DIGIT_1    0x06
#define TM1650_DIGIT_2    0x5B
#define TM1650_DIGIT_3    0x4F
#define TM1650_DIGIT_4    0x66
#define TM1650_DIGIT_5    0x6D
#define TM1650_DIGIT_6    0x7D
#define TM1650_DIGIT_7    0x07
#define TM1650_DIGIT_8    0x7F
#define TM1650_DIGIT_9    0x6F
#define TM1650_DIGIT_A    0x77
#define TM1650_DIGIT_B    0x7C
#define TM1650_DIGIT_C    0x39
#define TM1650_DIGIT_D    0x5E
#define TM1650_DIGIT_E    0x79
#define TM1650_DIGIT_F    0x71
#define TM1650_DIGIT_DASH 0x40
#define TM1650_DIGIT_BLANK 0x00

// 7-segment digit patterns
static const uint8_t digit_patterns[] = {
    TM1650_DIGIT_0, TM1650_DIGIT_1, TM1650_DIGIT_2, TM1650_DIGIT_3,
    TM1650_DIGIT_4, TM1650_DIGIT_5, TM1650_DIGIT_6, TM1650_DIGIT_7,
    TM1650_DIGIT_8, TM1650_DIGIT_9, TM1650_DIGIT_A, TM1650_DIGIT_B,
    TM1650_DIGIT_C, TM1650_DIGIT_D, TM1650_DIGIT_E, TM1650_DIGIT_F,
    TM1650_DIGIT_DASH, TM1650_DIGIT_BLANK
};

// Display positions
static const uint8_t display_positions[] = {
    TM1650_POS1, TM1650_POS2, TM1650_POS3, TM1650_POS4
};

/* USER CODE END 0 */

/*----------------------------------------------------------------------------*/
/* TM1650 Functions                                                          */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */

/**
  * @brief  Initialize TM1650 display
  * @retval None
  */
void TM1650_Init(void)
{
    // Initialize software I2C
    Soft_I2C_Init();
    
    // Clear display
    TM1650_Clear();
    
    // Turn on display with default brightness
    TM1650_DisplayOn();
}

/**
  * @brief  Turn on TM1650 display
  * @retval None
  */
void TM1650_DisplayOn(void)
{
    // 按照TM1650数据手册时序：command1 + command2 (连续两字节传输)
    Soft_I2C_Start();
    // Soft_I2C_SendByte(TM1650_I2C_ADDR);  // 数据手册未要求发送地址
    Soft_I2C_SendByte(TM1650_CMD_DATA_CMD);                    // Command1: 数据命令 0x48H
    Soft_I2C_SendByte(TM1650_CMD_DISPLAY_ON | 0x08);          // Command2: 开显示，亮度级3
    Soft_I2C_Stop();
}

/**
  * @brief  Turn off TM1650 display
  * @retval None
  */
void TM1650_DisplayOff(void)
{
    Soft_I2C_Start();
    // Soft_I2C_SendByte(TM1650_I2C_ADDR);  // 数据手册未要求发送地址
    Soft_I2C_SendByte(TM1650_CMD_DISPLAY_OFF);
    Soft_I2C_Stop();
}

/**
  * @brief  Set display brightness (0-7)
  * @param  brightness: Brightness level (0-7)
  * @retval None
  */
void TM1650_SetBrightness(uint8_t brightness)
{
    if (brightness > 7) brightness = 7;
    
    // 按照TM1650数据手册时序：command1 + command2 (连续两字节传输)
    Soft_I2C_Start();
    // Soft_I2C_SendByte(TM1650_I2C_ADDR);  // 数据手册未要求发送地址
    Soft_I2C_SendByte(TM1650_CMD_DATA_CMD);                    // Command1: 数据命令 0x48H
    Soft_I2C_SendByte(TM1650_CMD_DISPLAY_ON | (brightness << 1)); // Command2: 开显示，设置亮度
    Soft_I2C_Stop();
}

/**
  * @brief  Write digit to specific position
  * @param  position: Display position (0-3)
  * @param  digit: Digit pattern (0-15 for 0-F)
  * @retval None
  */
void TM1650_WriteDigit(uint8_t position, uint8_t digit)
{
    if (position > 3) return;
    if (digit > 17) digit = 17;  // 0-15 for digits, 16 for dash, 17 for blank
    
    // 按照TM1650数据手册时序：command1 + command2 + addr + data (连续四字节传输)
    Soft_I2C_Start();
    // Soft_I2C_SendByte(TM1650_I2C_ADDR);  // 数据手册未要求发送地址
    Soft_I2C_SendByte(TM1650_CMD_DATA_CMD);                    // Command1: 数据命令 0x48H (等待ACK)
    Soft_I2C_SendByte(TM1650_CMD_DISPLAY_ON | 0x08);          // Command2: 开显示，亮度级3 (等待ACK)
    Soft_I2C_SendByte(display_positions[position]);           // 显存地址 (等待ACK)
    Soft_I2C_SendByte(digit_patterns[digit]);                 // 显示数据 (等待ACK)
    Soft_I2C_Stop();
}

/**
  * @brief  Write number to display (0-9999)
  * @param  number: Number to display (0-9999)
  * @retval None
  */
void TM1650_WriteNumber(uint16_t number)
{
    uint8_t digits[4];
    uint8_t i;
    
    // Extract digits
    digits[0] = (number / 1000) % 10;
    digits[1] = (number / 100) % 10;
    digits[2] = (number / 10) % 10;
    digits[3] = number % 10;
    
    // 按照正确的I2C时序：每发送一个字节后等待ACK
    Soft_I2C_Start();
    // Soft_I2C_SendByte(TM1650_I2C_ADDR);  // 数据手册未要求发送地址
    Soft_I2C_SendByte(TM1650_CMD_DATA_CMD);                    // Command1: 数据命令 0x48H (等待ACK)
    Soft_I2C_SendByte(TM1650_CMD_DISPLAY_ON);          // Command2: 开显示，亮度级3 (等待ACK)
    Soft_I2C_Stop();
    // 连续写入四位数字，每发送一个字节后等待ACK
    for (i = 0; i < 4; i++)
    {
        Soft_I2C_Start();
        Soft_I2C_SendByte(display_positions[i]);               // 显存地址 (等待ACK)
        Soft_I2C_SendByte(digit_patterns[digits[i]]);          // 显示数据 (等待ACK)   
           
        Soft_I2C_Stop();
    }
     
}

/**
  * @brief  Write string to display (up to 4 characters)
  * @param  str: String to display
  * @retval None
  */
void TM1650_WriteString(char* str)
{
    uint8_t i, len = 0;
    char c;
    
    // Calculate string length
    while (str[len] != '\0' && len < 4) len++;
    
    // Write characters
    for (i = 0; i < 4; i++)
    {
        if (i < len)
        {
            c = str[i];
            
            // Convert character to digit pattern
            if (c >= '0' && c <= '9')
            {
                TM1650_WriteDigit(i, c - '0');
            }
            else if (c >= 'A' && c <= 'F')
            {
                TM1650_WriteDigit(i, c - 'A' + 10);
            }
            else if (c >= 'a' && c <= 'f')
            {
                TM1650_WriteDigit(i, c - 'a' + 10);
            }
            else if (c == '-')
            {
                TM1650_WriteDigit(i, 16); // Use dash pattern
            }
            else
            {
                TM1650_WriteDigit(i, 17); // Use blank pattern
            }
        }
        else
        {
            TM1650_WriteDigit(i, 17); // Blank
        }
    }
}

/**
  * @brief  Clear display
  * @retval None
  */
void TM1650_Clear(void)
{
    uint8_t i;
    
    for (i = 0; i < 4; i++)
    {
        TM1650_WriteDigit(i, 17); // Blank pattern
    }
}

/* USER CODE END 1 */

/* USER CODE BEGIN 2 */

/* USER CODE END 2 */
